﻿///////////////////////////////////////////////////////////////////////////////
// File:        Thread.cc
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////

#include <cassert>

#if defined(__WINDOWS__)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#elif defined(__LINUX__)
#include <unistd.h>
#endif

#include "nio/base/Thread.hpp"
using namespace nio::base;


Thread::Thread()
    : id_(0)
    , state_(READY)
#if defined(__WINDOWS__)
    , handle_(-1L)
#endif
{

}

Thread::~Thread()
{

}

bool Thread::start()
{
#if defined(__WINDOWS__)
    handle_ = ::_beginthreadex(NULL, 0, Thread::thread_proc, this, 0, &id_);
    return handle_ != -1L;
#elif defined(__LINUX__)
    return (::pthread_create(&id_, NULL, Thread::thread_proc, this) == 0);
#endif
}

void Thread::join()
{
#if defined(__WINDOWS__)
    assert(handle_ != -1L);
    ::WaitForSingleObject(HANDLE(handle_), INFINITE);
    ::CloseHandle(HANDLE(handle_));
    handle_ = -1L;
#elif defined(__LINUX__)
    ::pthread_join(id_, NULL);
#endif
}

bool Thread::joinable()
{
#if defined(__WINDOWS__)
    return (handle_ != -1L);
#elif defined(__LINUX__)
    return (id_ == 0);;
#endif
}

void Thread::detach()
{
#if defined(__WINDOWS__)
    assert(handle_ != -1L);
    ::CloseHandle(HANDLE(handle_));
    handle_ = -1L;
#elif defined(__LINUX__)
    ::pthread_detach(id_);
#endif
}

void Thread::sleep(unsigned int ms)
{
#if defined(__WINDOWS__)
    ::Sleep(DWORD(ms));
#elif defined(__LINUX__)
    ::usleep(int(ms * 1000));
#endif
}

Thread::id Thread::currentTid()
{
#if defined(__WINDOWS__)
    return ::GetCurrentThreadId();
#elif defined(__LINUX__)
    return ::pthread_self();
#endif
}

#if defined(__WINDOWS__)
unsigned int Thread::thread_proc(void* arg)
#elif defined(__LINUX__)
void* Thread::thread_proc(void* arg)
#endif
{
    assert(arg);
    Thread* pThread = static_cast<Thread*>(arg);
    pThread->setState(Thread::RUNNING);
    pThread->run();
    pThread->setState(Thread::EXIT);
    return 0;
}